package com.ls.controller;

import com.alibaba.fastjson.JSON;
import com.ls.annotation.LoginRequired;
import com.ls.entity.Page;
import com.ls.entity.User;
import com.ls.entity.vo.DiscussPostVo;
import com.ls.service.DiscussPostService;
import com.ls.service.FollowService;
import com.ls.service.LikeService;
import com.ls.service.UserService;
import com.ls.util.CommunityConstant;
import com.ls.util.CommunityUtil;
import com.ls.util.UserContextHolder;
import com.ls.util.R;
import com.qiniu.util.Auth;
import com.qiniu.util.StringMap;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.List;

/**
 * @author ls
 */
@Controller
@RequestMapping("/user")
public class UserController implements CommunityConstant {

    private static final Logger logger = LoggerFactory.getLogger(UserController.class);

    @Value("${community.path.domain}")
    private String domain;

    @Value("${server.servlet.context-path}")
    private String contextPath;

    @Autowired
    private UserService userService;

    @Autowired
    private UserContextHolder userContextHolder;

    @Autowired
    private LikeService likeService;

    @Autowired
    private FollowService followService;

    @Value("${qiniu.key.access}")
    private String accessKey;

    @Value("${qiniu.key.secret}")
    private String secretKey;

    @Value("${qiniu.bucket.header.name}")
    private String headerBucketName;

    @Value("${qiniu.bucket.header.url}")
    private String headerBucketUrl;

    @Autowired
    private DiscussPostService discussPostService;

    @LoginRequired
    @RequestMapping("/setting")
    public String toSetting(Model model) {
        // 生成上传文件名称
        String filename = CommunityUtil.generateUUID();
        // 设置相应信息
        StringMap policy = new StringMap();
        policy.put("returnBody", JSON.toJSONString(R.ok()));
        // 生成上传凭证
        Auth auth = Auth.create(accessKey, secretKey);
        String uploadToken = auth.uploadToken(headerBucketName, filename, 3600, policy);
        model.addAttribute("uploadToken", uploadToken);
        model.addAttribute("filename", filename);
        return "site/setting";
    }

    /**
     * 功能描述: <br>
     * 更新头像路径
     *
     * @param filename
     * @return {@link R}
     * @author ls
     * @date 2021/8/28 16:05
     */
    @PostMapping("header/url")
    @ResponseBody
    public R updateHeaderUrl(String filename) {
        if (StringUtils.isBlank(filename)) {
            return R.error("文件名为空!");
        }
        String url = headerBucketUrl + "/" + filename;
        userService.updateUserHeaderUrl(userContextHolder.getUser().getId(), url);
        return R.ok();
    }

    /**
     * 上传头像
     * 废弃，改为使用上传到七牛云
     *
     * @param headerImage 头像
     * @param model
     * @return
     */
    @Deprecated
    @LoginRequired
    @PostMapping("/uploadHeader")
    public String uploadHeader(MultipartFile headerImage, Model model) {
        if (headerImage == null) {
            model.addAttribute("error", "您还没有选中图片!");
            return "site/setting";
        }
        String filename = headerImage.getOriginalFilename();
        String suffix = filename.substring(filename.lastIndexOf("."));
        if (StringUtils.isBlank(suffix)) {
            model.addAttribute("error", "文件格式不正确!");
            return "site/setting";
        }

        //生成随机文件名
        filename = CommunityUtil.generateUUID() + suffix;

        String uploadPath = CommunityUtil.getUploadPath();
        // 确定文件存放路径
        File dest = new File(uploadPath + "/" + filename);
        // 路径不存在就创建路径
        File file = new File(uploadPath);
        if (!file.exists() && file.mkdirs()) {
            logger.info("创建目录 {} ", uploadPath);
        }
        try {
            // 存储文件
            headerImage.transferTo(dest);
        } catch (IOException e) {
            logger.error("上传文件失败：" + e.getMessage());
            throw new RuntimeException("上传文件失败，服务器发生异常！", e);
        }

        // 更新当前用户头像路径
        User user = userContextHolder.getUser();
        String headerUrl = domain + contextPath + "/user/header/" + filename;
        userService.updateUserHeaderUrl(user.getId(), headerUrl);

        return "redirect:/user/setting";
    }

    /**
     * 显示图片/下载文件
     * 改为直接访问七牛云
     *
     * @param filename 文件名
     * @param response 响应
     */
    @Deprecated
    @RequestMapping("/header/{filename}")
    public void getHeader(@PathVariable String filename, HttpServletResponse response) {
        // 服务器存放图片路径
        String uploadPath = CommunityUtil.getUploadPath();
        filename = uploadPath + "/" + filename;
        // 图片后缀
        String suffix = filename.substring(filename.lastIndexOf("."));
        // 设置响应图片
        response.setContentType("image/" + suffix);
        try (
                OutputStream os = response.getOutputStream();
                FileInputStream fis = new FileInputStream(filename);
        ) {
            byte[] buffer = new byte[1024];
            int b = 0;
            while ((b = fis.read(buffer)) != -1) {
                os.write(buffer, 0, b);
            }
        } catch (IOException e) {
            logger.error("读取头像失败！{}", e.getMessage());
        }

    }

    /**
     * 修改密码
     *
     * @param oldPassword 原密码
     * @param newPassword 新密码
     * @param model
     * @return 操作结果页面，跳转至登录页面
     */
    @LoginRequired
    @PostMapping("/updatePassword")
    public String updatePassword(String oldPassword, String newPassword, Model model, @CookieValue("ticket") String ticket) {

        User user = userContextHolder.getUser();
        if (StringUtils.isBlank(oldPassword) || !user.getPassword().equals(CommunityUtil.md5(oldPassword + user.getSalt()))) {
            model.addAttribute("passwordError", "原密码不正确！");
            return "site/setting";
        }
        if (StringUtils.isBlank(newPassword)) {
            model.addAttribute("passwordError", "新密码为空！");
            return "site/setting";
        }


        // 修改密码
        userService.updateUserPassword(user.getId(), CommunityUtil.md5(newPassword + user.getSalt()));
        model.addAttribute("msg", "您的密码已经修改成功，请重新登录！");
        model.addAttribute("target", "/toLogin");

        // 退出登录
        userService.logout(ticket);

        return "site/operate-result";
    }

    /**
     * 个人主页
     *
     * @param userId 用户Id
     * @param model
     * @return
     */
    @GetMapping("/profile/{userId}")
    public String getProfilePage(@PathVariable("userId") int userId, Model model) {
        // 详情页用户
        User user = userService.queryUserById(userId);
        if (user == null) {
            throw new RuntimeException("该用户不存在!");
        }
        // 用户
        model.addAttribute("user", user);
        // 点赞数
        int likeCount = likeService.getUserLikeCount(userId);
        model.addAttribute("likeCount", likeCount);

        // 关注数量
        long followeeCount = followService.getFolloweeCount(userId, ENTITY_TYPE_USER);
        model.addAttribute("followeeCount", followeeCount);
        // 粉丝数量
        long followerCount = followService.getFollowerCount(ENTITY_TYPE_USER, userId);
        model.addAttribute("followerCount", followerCount);
        // 是否已关注
        boolean hasFollowed = false;
        // 登录了
        if (userContextHolder.getUser() != null) {
            hasFollowed = followService.hasFollowed(userContextHolder.getUser().getId(), ENTITY_TYPE_USER, userId);
        }
        model.addAttribute("hasFollowed", hasFollowed);

        return "site/profile";
    }


    /**
     * 功能描述: <br>
     * 个人发布帖子
     *
     * @param userId
     * @return {@link String}
     * @author ls
     * @date 2021/8/28 19:59
     */
    @GetMapping("/profile/{userId}/post")
    public String toMyPostPage(@PathVariable("userId") int userId, Page page, Model model) {

        List<DiscussPostVo> discussPostVos = discussPostService.queryDiscussPosts(userId, page.getStartIndex(), page.getPageSize(), 0);

        int userPostCount = discussPostService.queryDiscussPostRows(userId);
        model.addAttribute("discussPostVos", discussPostVos);
        model.addAttribute("user", userService.queryUserById(userId));
        model.addAttribute("userPostCount", userPostCount);
        // 设置分页信息
        page.setPath(String.format("/user/profile/%d/post", userId));
        page.setTotalCount(userPostCount);

        return "site/my-post";
    }

}
